from django.shortcuts import render_to_response, get_object_or_404
from django.contrib.auth.decorators import login_required, permission_required
from django.template.context import RequestContext
from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponseRedirect
from django.views.generic.create_update import delete_object, update_object, create_object
from jrcmodel.models import CST, TimeLevel, Market, Portfolio, MyConstants, Asset,\
    JrcParameter, JrcSystem
from symbol import parameters
from django.views.generic.edit import DeleteView, CreateView, UpdateView
from django.views.generic.list import ListView
from django.views.generic.base import TemplateView
from django.forms.models import ModelForm
from django import forms
from jrcshared.models import JrcPermission


#TODO: Change generic-based functions to generic classes

class ForexFuturesCsts:
    Forex = None
    Futures = None

class CstsViewModel:
    Tested = ForexFuturesCsts()
    Implemented = ForexFuturesCsts()
    SortedOut = ForexFuturesCsts()
    Deleted = ForexFuturesCsts()

class GetCstsListView(ListView):
    """ Display list of CSTs items, used from Ajax """
    
    template_name = "portadmin/getcstsnew.html"
    
    def get_queryset(self):
        csts = CST.objects.all()
        
        try:
#            statusId = int(request.GET.get("status_id", "0"))
            statusId = int(self.request.GET.get("status_id", "0"))
        except ValueError:
            statusId = 0

        if statusId is not 0:
            csts = csts.filter(status_id = statusId)
            
        try:
            timelevel_id = int(self.request.GET.get("timelevel_id", "0"))
        except ValueError:
            timelevel_id = 0
            
        if timelevel_id != 0:
            csts = csts.filter(tmlvl_m = timelevel_id)
            
#        try:
#            market_direction_1 = int(self.request.GET.get("market_direction_1", "0"))
#        except ValueError:
#            market_direction_1 = 0
#            
#        if market_direction_1 != 0:
#            csts = csts.filter(market_direction_1 = market_direction_1)
#            
#        try:
#            market_direction_2 = int(self.request.GET.get("market_direction_2", "0"))
#        except ValueError:
#            market_direction_2 = 0
#            
#        if market_direction_2 != 0:
#            csts = csts.filter(market_direction_2 = market_direction_2)

        ar_csts = {}
        forex_futures = ForexFuturesCsts()
        forex_futures.Forex = csts.filter(market_direction_1__market_id__asset__name = "Forex")
        forex_futures.Futures = csts.filter(market_direction_1__market_id__asset__name = "Futures")
        ar_csts["MyConstants.CST_STATUS_IMPLEMENTED"] = forex_futures
        ar_csts["MyConstants.CST_STATUS_TESTED"] = forex_futures
        ar_csts["MyConstants.CST_STATUS_SORTDE OUT"] = forex_futures
        ar_csts["MyConstants.CST_STATUS_DELETED"] = forex_futures
#        ar_csts[MyConstants.CST_STATUS_DELETED] = [csts, csts]
        
        csts_view = CstsViewModel()
        csts_view.Deleted.Forex = csts.filter(status_id = MyConstants.CST_STATUS_DELETED).filter(market_direction_1__market_id__asset__name = "Forex")
        csts_view.Deleted.Futures = csts.filter(status_id = MyConstants.CST_STATUS_DELETED).filter(market_direction_1__market_id__asset__name = "Futures")
        csts_view.Tested.Forex = csts.filter(status_id = MyConstants.CST_STATUS_TESTED).filter(market_direction_1__market_id__asset__name = "Forex")
        csts_view.Tested.Futures = csts.filter(status_id = MyConstants.CST_STATUS_TESTED).filter(market_direction_1__market_id__asset__name = "Futures")
        csts_view.Implemented.Forex = csts.filter(status_id = MyConstants.CST_STATUS_IMPLEMENTED).filter(market_direction_1__market_id__asset__name = "Forex")
        csts_view.Implemented.Futures = csts.filter(status_id = MyConstants.CST_STATUS_IMPLEMENTED).filter(market_direction_1__market_id__asset__name = "Futures")
        csts_view.SortedOut.Forex = csts.filter(status_id = MyConstants.CST_STATUS_SORTED_OUT).filter(market_direction_1__market_id__asset__name = "Forex")
        csts_view.SortedOut.Futures = csts.filter(status_id = MyConstants.CST_STATUS_SORTED_OUT).filter(market_direction_1__market_id__asset__name = "Futures")
        return csts_view

class GetSystemListView(ListView):
    """ Displays list of JrcSystem items, used from Ajax """
    
#    queryset = JrcSystem.objects.all()
    template_name = "portadmin/getsystems.html"
    
    def get_queryset(self):
        systems = JrcSystem.objects.all()
        
        status_id = self.request.GET.get("status_id")
        try:
            status_id = int(status_id)
        except (TypeError, ValueError):
            status_id = 0
            
        if status_id > 0:
            systems = systems.filter(status_id = status_id)
        
        return systems 

class ParameterForm(forms.ModelForm):
    class Meta:
        model = JrcParameter
        exclude = ("jrc_key")

class UpdateParameterView(UpdateView):
    model = JrcParameter
    form_class = ParameterForm
    template_name = "portadmin/jrcparameter_form.html"
    success_url = "/portadmin/parameters/"

class CreateParameterView(CreateView):
    form_class = ParameterForm
#    model = JrcParameter
    template_name = "portadmin/jrcparameter_form.html"
    success_url = "/portadmin/parameters/"
    

class DeletePortfolioView(DeleteView):
    model = Portfolio
    template_name = "portadmin/portfolio_confirm_delete.html"
    success_url = "/portadmin/portfolios/"

class DeleteCstView(DeleteView):
    """ Provides wizard to delete CST object (handles linked JrcParameter) """
    model = CST
    context_object_name = "cst"
    template_name = "portadmin/deletecst.html"
    success_url = "/portadmin/csts/"
    
    def get_context_data(self, **kwargs):
        context = super(DeleteView, self).get_context_data(**kwargs);
        
        # To pass quantity of linked CST to determine should we move
        context["csts_for_market_1_count"] = 0
        context["csts_for_market_2_count"] = 0
        # If ass JrcParameters are connected with other CST
        context["allow_delete"] = True
        
        pk = int(context["cst"].pk)
        print "PK to exclude from CST connected to JrcParameter is #%d" % pk
        m1 = context["cst"].market_direction_1


        # Select all CSTs which are connected to JrcParameter except current CST
        context["csts_for_market_1"] = CST.objects.filter(market_direction_1 = m1).exclude(pk = pk)
        
        # Prevent delete of CST if its JrcParameter is not linked w/ other CST
        if len( context["csts_for_market_1"] ) < 1:
            context["allow_delete"] = False
        
        m2 = context["cst"].market_direction_2
        print "Market direction 2 is linked with JrcParameter #%s" % m2
        if m2 != None:
            # Select all CSTs which are connected to JrcParameter except current CST
            context["csts_for_market_2"] = CST.objects.filter(market_direction_2 = m2).exclude(pk = pk)
            # Prevent delete of CST if its JrcParameter is not linked w/ other CST
            if len( context["csts_for_market_2"] ) < 1:
                context["allow_delete"] = False


#        print markets_1
#        context["cst_linked_w_market_1"] = CST.objects.filter(market_direction_1 = market_1_id)
#        print context["cst_linked_w_market_1"]
        
        return context
    
#    def get_context_data(self, **kwargs):
#        return super(DeleteView).get_context_data(**kwargs)


class CreateMarketView(CreateView):
    model = Market
    context_object_name = "market"
#    template_name = "portadmin/addmarket.html"
    template_name = "portadmin/editmarket.html"
    success_url = "/portadmin/markets/"
    
    def get_context_data(self, **kwargs):
        context = super(CreateView, self).get_context_data(**kwargs)
        context["hours"] = range(0, 24)
        context["minutes"] = (0, 15, 30, 45)
#        print "Hours: %s" % context["hours"]
        return context

class ListMarketsView(ListView):
    model = Market
    context_object_name = "market_list"
    template_name = "portadmin/getmarkets.html"
    
    def get_queryset(self):
        qs = Market.objects.all()

        # Check if we have smth to filter
        try:
            statusId = int(self.request.GET.get("status_id", 0))
        except ValueError:
            statusId = 0
        if statusId != 0:
            qs = qs.filter(status_id = statusId)

        try:
            assetId = int(self.request.GET.get("asset_id", 0))
        except ValueError:
            assetId = 0
        if assetId != 0:
            qs = qs.filter(asset__id = assetId)
            
        qs = qs.order_by("-asset__priority")
            
        return qs

class UpdateMarketView(UpdateView):
    model = Market
    context_object_name = "market"
    template_name = "portadmin/editmarket.html"
    success_url = "/portadmin/markets/"

    def get_context_data(self, **kwargs):
        context = super(UpdateView, self).get_context_data(**kwargs)
        context["hours"] = range(0, 24)
        context["minutes"] = (0, 15, 30, 45)
        return context
        
class DeleteMarketView(DeleteView):
    model = Market
    context_object_name = "market"
    template_name = "portadmin/deletemarket.html"
    success_url = "/portadmin/markets/"

class MarketView(TemplateView):
    template_name = "portadmin/markets.html"
    
    def get_context_data(self, **kwargs):
        context = {}
        context["assets"] = Asset.objects.all()
        context["page"] = 1
#        print context["assets"]
        return context
        


class ParameterViewModel:
    is_free = True
    disabled = ""
    name = ""
    parameter_pk = 0
    
    def __unicode__(self):
        return "#%d. %s %s" % (self.pk, self.name, self.disabled)

class EditCstView(UpdateView):
    model = CST
    template_name = "portadmin/editcst.html"
    success_url = "/portadmin/csts/"
    
    def get_context_data(self, **kwargs):
        free_csts_1 = {}
        free_csts_2 = {}
        
        # Select all available JrcParameter
        parameters = JrcParameter.objects.all().filter(status_id = MyConstants.STATUS_APPROVED)
        for p in parameters:
#            print "JrcParameter #%d has market #%d" % (p.pk, p.market_id.pk)
            csview = ParameterViewModel()
            csview.parameter_pk = p.pk
            csview.name = p
            csview.disabled = ""
            free_csts_1[csview.parameter_pk] = csview
            free_csts_2[csview.parameter_pk] = csview

        print "Free CSTs for market direction 1:"
        for p in free_csts_1.values():
            print "#%d. %s (%s)" % (p.parameter_pk, p.name, p.disabled)

        # Select all CSTs, even deleted to prevent duplicates
        csts = CST.objects.all() #.filter(status_id = MyConstants.STATUS_APPROVED)
        for cst in csts:
#            print "Need to mark JrcParameter #%d as used" % cst.market_direction_1.pk
#            if cst.market_direction_2 != None:
#                print "Need to mark market_direction_2: %d" % cst.pk
#            else:
#                print "No market_direction_2"

            if free_csts_1.has_key(cst.market_direction_1_id):
                free_csts_1[cst.market_direction_1_id].disabled = "disabled"

#            if free_csts_1.has_key(cst.market_direction_1.pk):
#                free_csts_1[cst.market_direction_1.pk].disabled = "disabled"
            if (cst.market_direction_2 != None) and free_csts_2.has_key(cst.market_direction_2.pk):
                free_csts_2[cst.market_direction_2.pk].disabled = "disabled"
        
        context = super(UpdateView, self).get_context_data(**kwargs)
        context["free_csts_1"] = free_csts_1
        context["free_csts_2"] = free_csts_2
        return context

class AddCstView(CreateView):
    model = CST
    template_name = "portadmin/addcst.html"
    success_url = "/portadmin/csts/"

    def get_context_data(self, **kwargs):
        free_csts_1 = {}
        free_csts_2 = {}
        
        # Select all available JrcParameter
        parameters = JrcParameter.objects.all().filter(status_id = MyConstants.STATUS_APPROVED)
        for p in parameters:
#            print "JrcParameter #%d has market #%d" % (p.pk, p.market_id.pk)
            csview = ParameterViewModel()
            csview.parameter_pk = p.pk
            csview.name = p
            free_csts_1[csview.parameter_pk] = csview
            free_csts_2[csview.parameter_pk] = csview

#        print "Free Parameters for market_direct_1:"
#        for cst in free_csts_1.values():
#            print "#%d. %s %s" % (cst.parameter_pk, cst.name, cst.disabled)

#        print "Free Parameters for market_direct_2:"
#        for cst in free_csts_2.values():
#            print "#%d. %s %s" % (cst.parameter_pk, cst.name, cst.disabled)

        # Select all CSTs, even deleted to prevent duplicates
        csts = CST.objects.all() #.filter(status_id = MyConstants.STATUS_APPROVED)
        for cst in csts:
#            print "Need to mark JrcParameter #%d as used" % cst.market_direction_1.pk
#            if cst.market_direction_2 != None:
#                print "Need to mark market_direction_2: %d" % cst.pk
#            else:
#                print "No market_direction_2"

            if free_csts_1.has_key(cst.market_direction_1_id):
                free_csts_1[cst.market_direction_1_id].disabled = "disabled"
#            if free_csts_1.has_key(cst.market_direction_1.pk):
#                free_csts_1[cst.market_direction_1.pk].disabled = "disabled"
            if (cst.market_direction_2 != None) and free_csts_2.has_key(cst.market_direction_2.pk):
                free_csts_2[cst.market_direction_2.pk].disabled = "disabled"
        
        context = super(CreateView, self).get_context_data(**kwargs);
        context["free_csts_1"] = free_csts_1
        context["free_csts_2"] = free_csts_2
        return context

#def addcst(request):
#    return create_object(request, model = CST, template_name = "portadmin/addcst.html", post_save_redirect = "/portadmin/parameters/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def addportfolio(request):
    return create_object(request, model = Portfolio, template_name = "portadmin/addportfolio.html", post_save_redirect = "/portadmin/portfolios/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def addparameter(request):
    return create_object(request, model = JrcParameter, template_name = "portadmin/addparameter.html", post_save_redirect = "/portadmin/parameters/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def addsystem(request):
    return create_object(request, model = JrcSystem, template_name = "portadmin/addsystem.html", post_save_redirect = "/portadmin/systems/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def editparameter(request, id):
    return update_object(request, model = JrcParameter, object_id = id, template_name = "portadmin/editparameter.html", post_save_redirect = "/portadmin/parameters/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def editsystem(request, id):
    return update_object(request, model = JrcSystem, object_id = id, template_name = "portadmin/editsystem.html", post_save_redirect = "/portadmin/systems/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def editcst(request, id):
    return update_object(request, model = CST, object_id = id, template_name = "portadmin/editcst.html", post_save_redirect = "/portadmin/csts/", login_required = True)

@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def editportfolio(request, id):
    return update_object(request, model = Portfolio, object_id = id, template_name = "portadmin/editportfolio.html", post_save_redirect = "/portadmin/portfolios/", login_required = True)


@permission_required(JrcPermission.TRADINGSYSTEMS_CHANGE, "/accounts/denied/")
def deletecst(request, id):
    item = get_object_or_404(CST, pk = id)
    if request.method == "POST":
        item.status_id = MyConstants.STATUS_DELETED
        item.save()
        return HttpResponseRedirect("/portadmin/csts/")

    return render_to_response("portadmin/deletecst.html", {"item": item}, context_instance = RequestContext(request))

@login_required
def parameters(request):
    page = 1

    #
    # Load everything for menu
    #
    systems = JrcSystem.objects.all()
    assets = Asset.objects.all()
    timelevels = TimeLevel.objects.all()

    if request.GET.has_key("asset_id"):
        markets = Market.objects.get(asset_id = request.GET.get("asset_id"))
    else:
        markets = Market.objects.all()
    
    
    return render_to_response(
        "portadmin/parameters.html"
        , {
           "assets": assets
           , "markets": markets
           , "systems": systems
           , "timelevels": timelevels
           , "page": page
        })

@login_required
def viewcst(request, pk):
    cst = CST.objects.get(pk = pk)
    return render_to_response(
        "portadmin/viewcst.html"
        , {
            "cst": cst
        }
        , context_instance = RequestContext(request)
    )

@login_required
def csts(request, page):
    paginator = Paginator(CST.objects.all(), 20)
    print "Total pages %d" % paginator.num_pages
    
#    try:
#        page = int(request.GET.get("page", "1"))
#    except ValueError:
#        page = 1

    try:
        object_list = paginator.page(page)
    except (EmptyPage, InvalidPage):
        object_list = paginator.page(paginator.num_pages)
    
    timelevels = TimeLevel.objects.filter(status_id = MyConstants.STATUS_APPROVED)
    parameters = JrcParameter.objects.filter(status_id = MyConstants.STATUS_APPROVED).order_by("-priority")
    
    return render_to_response("portadmin/csts.html"
                              , {
                                 "paginator": paginator
                                 , "page": page
                                 , "timelevels": timelevels
                                 , "parameters": parameters
                                 }
                              , context_instance = RequestContext(request)
                              )

@login_required
def systems(request):
    return render_to_response("portadmin/systems.html")

@login_required
def portfolios(request):
    ps = Portfolio.objects.all() 
    
    try:
        statusId = int(request.GET.get("status_id", "0"))
    except ValueError:
        statusId = 0
    
    if statusId is not 0:
        ps = ps.filter(status_id = statusId)
        
    paginator = Paginator(ps, 1)

    return render_to_response("portadmin/portfolios.html"
                              , {"paginator": paginator}
                              , context_instance = RequestContext(request)
                              )

def getparameters(request, page):
    qs = JrcParameter.objects.all()

    try:
        statusId = int(request.GET.get("status_id", "0"))
    except ValueError:
        statusId = 0
    
    if statusId != 0:
        print "Filtering JrcParameter table using status ID: %d" % statusId
        qs = qs.filter(status_id = statusId)

    try:
        systemId = int(request.GET.get("system_id", "0"))
    except ValueError:
        systemId = 0
    
    if systemId != 0:
        print "Filtering JrcParameter table using system ID: %d" % systemId
        qs = qs.filter(system_id = systemId)

    try:
        assetId = int(request.GET.get("asset_id", "0"))
    except ValueError:
        assetId = 0
    
    if assetId != 0:
        print "Filtering JrcParameter table using asset class ID: %d" % assetId
        qs = qs.filter(market_id__asset = assetId)

    try:
        marketId = int(request.GET.get("market_id", "0"))
    except ValueError:
        marketId = 0
    
    if marketId != 0:
        print "Filtering JrcParameter table using market ID: %d" % marketId
        qs = qs.filter(market_id = marketId)

    directionId = request.GET.get("direction", "0")
    
    if directionId != "0":
        print "Filtering JrcParameter table using direction ID: %s" % directionId
        qs = qs.filter(direction_id = directionId)

    try:
        cashOrFuture = request.GET.get("cof", "")
    except ValueError:
        cashOrFuture = ""
    
    if cashOrFuture in "CF":
        print "Filtering JrcParameter table using Cash/Future: %s" % cashOrFuture
        qs = qs.filter(cash_or_future = cashOrFuture)

    qs = qs.order_by("-jrc_key")

    paginator = Paginator(qs, 20)
    return render_to_response("portadmin/getparameters.html"
                                , {"paginator": paginator
                                    , "object_list": qs
                                });

def getportfolios(request, page):
    ps = Portfolio.objects.all() 
    
    try:
        statusId = int(request.GET.get("status_id", "0"))
    except ValueError:
        statusId = 0
    
    if statusId is not 0:
        ps = ps.filter(status_id = statusId)
        
    paginator = Paginator(ps, 20)
    try:
        object_list = paginator.page(page).object_list
    except (EmptyPage, InvalidPage):
        object_list = paginator.page(paginator.num_pages).object_list
    
#    print "Page: %s" % page
#    print paginator.page_range

    return render_to_response("portadmin/getportfolios.html"
                              , {"paginator": paginator
                                 , "object_list": object_list
                                 , "page": page
                                 }
                              , context_instance = RequestContext(request)
                              )

def getcsts(request, page):
    csts = CST.objects.all()#.filter(market_direction_1__market_id__asset__name = "Forex")
#    items_futures = CST.objects.all().filter(market_direction_1__market_id__asset__name = "Futures")
    
    try:
        statusId = int(request.GET.get("status_id", "0"))
    except ValueError:
        statusId = 0
    
    if statusId is not 0:
        csts = csts.filter(status_id = statusId)
        
    try:
        timelevel_id = int(request.GET.get("timelevel_id", "0"))
    except ValueError:
        timelevel_id = 0
        
    if timelevel_id != 0:
        csts = csts.filter(tmlvl_m = timelevel_id)
        
    try:
        market_direction_1 = int(request.GET.get("market_direction_1", "0"))
    except ValueError:
        market_direction_1 = 0
        
    if market_direction_1 != 0:
        csts = csts.filter(market_direction_1 = market_direction_1)
        
    try:
        market_direction_2 = int(request.GET.get("market_direction_2", "0"))
    except ValueError:
        market_direction_2 = 0
        
    if market_direction_2 != 0:
        csts = csts.filter(market_direction_2 = market_direction_2)
        
    csts_forex = csts.filter(market_direction_1__market_id__asset__name = "Forex")
    csts_futures = csts.filter(market_direction_1__market_id__asset__name = "Futures")
        
#    paginator = Paginator(csts, 100)
#    try:
#        csts_forex = paginator.page(page).object_list
#    except (EmptyPage, InvalidPage):
#        csts_forex = paginator.page(paginator.num_pages).object_list

    print "Items %s" % csts_forex
#    print "Page: %s" % page
#    print paginator.page_range

    return render_to_response("portadmin/getcsts.html"
                              , {
#                                 "paginator": paginator,
                                 "csts_forex": csts_forex,
                                 "csts_futures": csts_futures,
                                 "page": page
                                 }
                              , context_instance = RequestContext(request)
                              )

